package inge_soft.gestoriusNuevo.business.controller.implementation;

import inge_soft.gestoriusNuevo.business.logic.ActividadFiltro;
import inge_soft.gestoriusNuevo.business.logic.ActividadMemoria;
import inge_soft.gestoriusNuevo.business.logic.SolicitudMemoria;
import inge_soft.gestoriusNuevo.business.logic.SolicitudOrganizadorFiltro;
import inge_soft.gestoriusNuevo.business.logic.implementation.ManejadorMail;
import inge_soft.gestoriusNuevo.business.service.abstraction.IActividadService;
import inge_soft.gestoriusNuevo.business.service.abstraction.IProcesarSolicitudService;
import inge_soft.gestoriusNuevo.business.service.abstraction.IServicioEvento;
import inge_soft.gestoriusNuevo.business.service.abstraction.IUsuarioService;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.Actividad;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.Estado;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.Evento;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.Institucion;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.SolicitudOrganizador;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.SolicitudOrganizadorLog;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.TipoActividad;
import inge_soft.gestoriusNuevo.persistence.entity.implementation.UsuarioRegistrado;
import inge_soft.gestoriusNuevo.support.Global;
import inge_soft.gestoriusNuevo.support.SecurityUtil;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;

import org.springframework.transaction.annotation.Transactional;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.ListModelList;

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class ListaActividadesViewModel {
	
	@WireVariable("actividadService")
	private IActividadService actividadService;

	// Son las solicitudes que se usan en el ZUL y estan
	// en memoria. Son una copia adaptada de las de BD
	private ListModelList<ActividadMemoria> actividadesMem;
	
	private ListModelList<ActividadMemoria> actividadesMemRespaldo;
	
	// Solicitud del ZUL seleccionada por el usuario
	private ActividadMemoria seleccionada;
	
	// Variable usada para determinar si hay cambios entre
	// las solicitudes de memoria y BD
	private boolean cambiosMemoria;
	
	// Lista de tipos posibles de una actividad
	private ListModelList<String> tipoActividades;
	
	// Lista de estados posibles de una actividad
	private ListModelList<String> estadoActividades;
	
	private List<String> acciones;
	
	private static final String NUEVO = "NUEVO";
	private static final String EDITAR = "EDITAR";
	private static final String VER = "VER";
	
	private ActividadFiltro actividadFilter = new ActividadFiltro();
	
	private boolean consultaFiltros = false;
	
	// FALTA ACA
	private Evento evento;
	
	
	@Init
	public void init() {
		
		Long idEvento = (Long) Sessions.getCurrent().getAttribute("evento");
		
		evento = actividadService.obtenerEvento(idEvento);
		
		/**
		 * Cargo todas los tipos de actividades
		 */
		List<TipoActividad> tipoAct = actividadService.obtenerTodosTiposActividad();
		tipoActividades = new ListModelList<String>();
		
		for(int i = 0; i < tipoAct.size(); i++){
			tipoActividades.add(tipoAct.get(i).getNombre());
		}
		
		/**
		 * Cargo todos los estados de una actividad
		 */
		List<Estado> tipoEst = actividadService.obtenerTodosEstados();
		estadoActividades = new ListModelList<String>();
		
		for(int i = 0; i < tipoEst.size(); i++){
			estadoActividades.add(tipoEst.get(i).getNombre());
		}
		
		/**
		 * Cargo todas las acciones de una actividad
		 */
		acciones = new ArrayList();
		acciones.add(NUEVO);
		acciones.add(EDITAR);
		acciones.add(VER);
	}
	
	
	/**
	 * Filtra las actividades segun los parametros de filtro de cada columna
	 */
	@NotifyChange("actividadesMem")
	@Command
	public void consultaFiltro() {
        consultaFiltros = true;
        
        String nombreActividad = actividadFilter.getNombreActividad();
        String nombreTipoActividad = actividadFilter.getNombreTipoActividad();
    	String nombreEstado = actividadFilter.getNombreEstado();
    	Date fechaInicio = actividadFilter.getFechaInicio();
    	Date fechaFin = actividadFilter.getFechaFin();
    	String docente = actividadFilter.getDocente();
        
        Iterator<ActividadMemoria> itSolMem = actividadesMemRespaldo.iterator();
        
        if(actividadesMem != null){
        	actividadesMem.clear();
        } else {
        	actividadesMem = new ListModelList<ActividadMemoria>();
        }
        
        boolean result;
        
        while(itSolMem.hasNext()){
        	result = true;
        	ActividadMemoria actMem = itSolMem.next();
        	
        	if(!nombreActividad.equals("")) {
            	result = result && (actMem.getNombreActividad().toUpperCase().contains(nombreActividad.toUpperCase()));
            	
            	
            }
        	if(!nombreTipoActividad.equals("")){
        		result = result && (actMem.getNombreTipoActividad().toUpperCase().contains(nombreTipoActividad.toUpperCase()));
        	}
        	if(!nombreEstado.equals("")){
        		result = result && (actMem.getNombreEstado().toUpperCase().contains(nombreEstado.toUpperCase()));
        	}
        	if(!docente.equals("")){
        		result = result && (actMem.getDocente().toUpperCase().contains(docente.toUpperCase()));
        	}
        	
        	if(fechaInicio != null){
        		result = result && (actMem.getFechaInicio().getTime() >= fechaInicio.getTime());
        	}
        	
        	if(fechaFin != null){
        		result = result && (actMem.getFechaFin().getTime() < fechaFin.getTime());
        	}
        	
        	if(result){
        		actividadesMem.add(actMem);
				//System.out.println(actMem.toString());
        	}
        }
        
        //System.out.println("Cantidad de actividades: " + actividadesMem.size());
        if((nombreActividad.equals("")) && (nombreTipoActividad.equals("")) && (nombreEstado.equals("")) 
        		&& (fechaInicio == null) && (fechaFin == null) && (docente.equals(""))){
        	consultaFiltros = false;
        }
    }

	/*
	 * Getter de solicitudesMem. Se encarga de convertir la lista de
	 * Actividades de la base de datos, a una lista equivalente en
	 * memoria (algunos atributos cambian su tipo)
	 */
	public ListModelList<ActividadMemoria> getActividadesMem() {
		if(consultaFiltros == false){
			ActividadMemoria actMem;
			cambiosMemoria = false;
			actividadesMem = new ListModelList<ActividadMemoria>();
			
			actividadesMemRespaldo = new ListModelList<ActividadMemoria>();
			
			// esta linea hay que cambiar cuando esten funcionando los filtros, por el parametro EVENTO
			List<Actividad> listaActividadesBD = actividadService.obtenerTodasActividades(evento);
					
			for (Actividad a : listaActividadesBD) {
					
				actMem = new ActividadMemoria();
				actMem.setActividadID(a.getId());
				actMem.setActividadModificada(false);
				actMem.setNombreActividad(a.getNombre());
				actMem.setNombreTipoActividad(a.getTipoActividad().getNombre());
				actMem.setNombreEstado(a.getEstado().getNombre());
				actMem.setFechaInicio(a.getFechaInicio());
				actMem.setFechaFin(a.getFechaFin());
				actMem.setDocente(a.getDocente());
				actividadesMem.add(actMem);
				
				actMem = new ActividadMemoria();
				actMem.setActividadID(a.getId());
				actMem.setActividadModificada(false);
				actMem.setNombreActividad(a.getNombre());
				actMem.setNombreTipoActividad(a.getTipoActividad().getNombre());
				actMem.setNombreEstado(a.getEstado().getNombre());
				actMem.setFechaInicio(a.getFechaInicio());
				actMem.setFechaFin(a.getFechaFin());
				actMem.setDocente(a.getDocente());
				actividadesMemRespaldo.add(actMem);
			}
		}
		return actividadesMem;
	}
	
	public ListModelList<String> getTipoActividades() {
		return tipoActividades;
	}
	
	public ListModelList<String> getEstadoActividades() {
		return estadoActividades;
	}
	
	public List<String> getAcciones() {
		return acciones;
	}

	public ActividadMemoria getSeleccionada() {
		return seleccionada;
	}

	public void setSeleccionada(ActividadMemoria seleccionada) {
		this.seleccionada = seleccionada;
	}

	public boolean isCambiosMemoria() {
		return cambiosMemoria;
	}

	public void setCambiosMemoria(boolean cambiosMemoria) {
		this.cambiosMemoria = cambiosMemoria;
	}
	
	public ActividadFiltro getActividadFilter() {
		return actividadFilter;
	}
	
	public String getNombreEvento(){
		return evento.getNombre();
	}

	/*
	 * Actualiza en la BD los elementos que esten en memoria y hallan
	 * sido modificados. Tambien crea los Log correspondientes
	 */
	@NotifyChange("cambiosMemoria")
	@Command
	@Transactional
	public void guardarActividadesEnBD() {
		cambiosMemoria = false;
		Actividad actBD;
		
		if (actividadesMem != null) {
			for (ActividadMemoria a : actividadesMem) {
				// solo cargo las solicitudes que fueron modificadas
				if (a.isActividadModificada()) {

					// primero actualizamos la solicitud en la BD
					actBD = actividadService.obtenerActividad(a.getActividadID());
					
					TipoActividad tipoAct = actividadService.obtenerTipoActividad(a.getNombreTipoActividad());
					actBD.setTipoActividad(tipoAct);
					
					Estado estado = actividadService.obtenerEstado(a.getNombreEstado());
					actBD.setEstado(estado);
					
					actBD.setNombre(a.getNombreActividad());
					actBD.setDocente(a.getDocente());
					actBD.setFechaInicio(a.getFechaInicio());
					actBD.setFechaFin(a.getFechaFin());
					
					actividadService.modificarActividad(actBD);
					
					a.setActividadModificada(false);
				}
			}
			
			//System.out.println("Cantidad de LOGs: " + procesarSolService.obtenerSolicitudesLog().size());
		}
	}

	/*
	 * Levanto la bandera de modificacion en la fila seleccionada
	 */
	@NotifyChange({ "seleccionada", "cambiosMemoria" })
	@Command
	public void actualizarActividad() {
		cambiosMemoria = true;
		seleccionada.setActividadModificada(true);
	}
	
	@Command
	public void verActividad(@BindingParam("actividadMemoria") ActividadMemoria actividad) {
		Sessions.getCurrent().setAttribute("ModoVentana", VER);
		Sessions.getCurrent().setAttribute("IdActividad", actividad.getActividadID());
		Executions.getCurrent().sendRedirect("index.zul?destino=FormularioActividadViewModel.zul","");
		System.out.println("VER");
	}
	
	@Command
	public void editarActividad(@BindingParam("actividadMemoria") ActividadMemoria actividad) {
		Sessions.getCurrent().setAttribute("ModoVentana", EDITAR);
		Sessions.getCurrent().setAttribute("IdActividad", actividad.getActividadID());
		Executions.getCurrent().sendRedirect("index.zul?destino=FormularioActividadViewModel.zul","");
		System.out.println("EDITAR");
	}
	
	@Command
	public void nuevaActividad() {
		Sessions.getCurrent().setAttribute("ModoVentana", NUEVO);
		Sessions.getCurrent().setAttribute("IdEvento", evento.getId());
		Executions.getCurrent().sendRedirect("index.zul?destino=FormularioActividadViewModel.zul","");
		System.out.println("NUEVA");
	}
	
	@Command
	public void volver() {
		Executions.getCurrent().sendRedirect("index.zul","");
		System.out.println("VOLVER");
	}
}
